-- Constants
TITAN_PANEL_UPDATE_BUTTON = 1;
TITAN_PANEL_UDPATE_TOOLTIP = 2;
TITAN_PANEL_UPDATE_ALL = 3;
TITAN_PANEL_LABEL_SEPARATOR = "  "

TITAN_PANEL_BUTTON_TYPE_TEXT = 1;
TITAN_PANEL_BUTTON_TYPE_ICON = 2;
TITAN_PANEL_BUTTON_TYPE_COMBO = 3;
TITAN_PANEL_BUTTON_TYPE_CUSTOM = 4;

TITAN_STANCESETS_ID = "StanceSets";
TITAN_STANCESETS_FREQUENCY = 1;

STANCESET_INDEX = 0;
STANCESET_MAX_STANCES = 5

BINDING_HEADER_STANCESETS = "Stance Sets"
BINDING_NAME_TOGGLESTANCESETSDLG = "Toggle Configuration Pane";
BINDING_NAME_STANCESETNEXT = "Equip Next Weapon Set";

StanceSetsOptions = {};

--UIPanelWindows["StanceSetsFrame"] = { area = "left", pushable = 5 }; 

function TitanOptionSlider_TooltipText(text, value) 
	return text .. GREEN_FONT_COLOR_CODE .. value .. FONT_COLOR_CODE_CLOSE;
end

function TitanPanelStanceSetsButton_OnLoad()
	this:RegisterEvent("VARIABLES_LOADED");
	-- register plugin
	this.registry = { 
		id = TITAN_STANCESETS_ID,
		version = "3.1.2.20300",
		menuText = STANCESETS_LOCALE["menu"],
		buttonTextFunction = "TitanPanelStanceSetsButton_GetButtonText",
		tooltipTitle = STANCESETS_LOCALE["tooltip"],
		tooltipTextFunction = "TitanPanelStanceSetsButton_GetTooltipText",
		frequency = TITAN_STANCESETS_FREQUENCY, 
		icon = "Interface\\Icons\\Ability_Warrior_ShieldWall",
		iconWidth = 16,
		savedVariables = {
			ShowIcon = 1,
			ShowLabelText = 1,
			ShowColoredText = TITAN_NIL
		}
	};

end

function TitanPanelStanceSetsButton_OnEvent()
	if(event == "VARIABLES_LOADED") then
		if (StanceSetsOptions.StanceSetsLocked == nil) then
			StanceSetsOptions.StanceSetsLocked = false;
		end
		if (StanceSetsOptions.ShowStance == nil) then
			StanceSetsOptions.ShowStance = true;
		end
	end
end

function TitanPanelStanceSetsButton_GetButtonText(id)
	local retstr = "";

	-- supports turning off labels
	if (TitanGetVar(TITAN_STANCESETS_ID, "ShowLabelText")) then
		if (StanceSetsOptions.ShowStance) then
			retstr =  STANCESETS_LOCALE["button"];
		else
			retstr =  STANCESETS_LOCALE["cbutton"];
		end
	end
	
	if (StanceSetsOptions.ShowStance) then
		if (TitanGetVar(TITAN_STANCESETS_ID, "ShowColoredText")) then	
			retstr = retstr .. TitanUtils_GetGreenText(StanceSets_GetCurrentForm());
		else
			retstr = retstr .. TitanUtils_GetNormalText(StanceSets_GetCurrentForm());
		end
	end

	return retstr;
end

function TitanPanelStanceSetsButton_GetTooltipText()
	local retstr = TitanUtils_GetGreenText("Hint: Left click to open Stance Sets");
	return retstr;
end

function TitanPanelRightClickMenu_PrepareStanceSetsMenu()
	TitanPanelRightClickMenu_AddTitle(TitanPlugins[TITAN_STANCESETS_ID].menuText);
	info = {};
	info.text = ATLAS_OPTIONS_SHOWSTANCE;
	info.func = StanceSetOptions_ShowStanceToggle;
	info.value = ATLAS_OPTIONS_SHOWSTANCE;
	info.checked = StanceSetsOptions.ShowStance;
	UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL);

	info = {};

	TitanPanelRightClickMenu_AddSpacer();	
	TitanPanelRightClickMenu_AddToggleIcon(TITAN_STANCESETS_ID);
	TitanPanelRightClickMenu_AddToggleLabelText(TITAN_STANCESETS_ID);
	TitanPanelRightClickMenu_AddToggleColoredText(TITAN_STANCESETS_ID);
	
	TitanPanelRightClickMenu_AddSpacer();	
	TitanPanelRightClickMenu_AddCommand(TITAN_PANEL_MENU_HIDE, TITAN_STANCESETS_ID, TITAN_PANEL_MENU_FUNC_HIDE);
end

function TitalPanelStanceSetsButton_OnClick(button)
	if ( button == "LeftButton" ) then
		StanceSets_Toggle();
	end
end

function StanceSetOptions_ShowStanceToggle()
	if(StanceSetsOptions.ShowStance) then
		StanceSetsOptions.ShowStance = false;
	else
		StanceSetsOptions.ShowStance = true;
	end
end

function StanceSets_StartMoving()
	if(not StanceSetsOptions.StanceSetsLocked) then
		StanceSetsFrame:StartMoving();
	end
end

function StanceSets_ToggleLock()
	if(StanceSetsOptions.StanceSetsLocked) then
		StanceSetsOptions.StanceSetsLocked = false;
		StanceSets_UpdateLock();
	else
		StanceSetsOptions.StanceSetsLocked = true;
		StanceSets_UpdateLock();
	end
end

function StanceSets_UpdateLock()
	if(StanceSetsOptions.StanceSetsLocked) then
		StanceSetsLockNorm:SetTexture("Interface\\AddOns\\Titan\\TitanStanceSets\\Images\\LockButton-Locked-Up");
		StanceSetsLockPush:SetTexture("Interface\\AddOns\\Titan\\TitanStanceSets\\Images\\LockButton-Locked-Down");
	else
		StanceSetsLockNorm:SetTexture("Interface\\AddOns\\Titan\\TitanStanceSets\\Images\\LockButton-Unlocked-Up");
		StanceSetsLockPush:SetTexture("Interface\\AddOns\\Titan\\TitanStanceSets\\Images\\LockButton-Unlocked-Down");
	end
end

function StanceSets_OnLoad()
	this:RegisterEvent("UPDATE_BONUS_ACTIONBAR");
	this:RegisterEvent("SPELLS_CHANGED");
	this:RegisterEvent("VARIABLES_LOADED");
	
	tinsert(UISpecialFrames, "StanceSetsFrame");
	UIPanelWindows["StanceSetsFrame"] = nil;
	StanceSetsFrame:RegisterForDrag("LeftButton");
	SlashCmdList["STANCESETS"] = StanceSets_SlashCmd;
	SLASH_STANCESETS1 = "/stancesets";
	
	StanceSets = { };
end

function StanceSets_OnShow()
	return StanceSets_UpdateAllStances();	
end

function StanceSets_OnEvent(event, arg1)
	if event == "UPDATE_BONUS_ACTIONBAR" then
		return StanceSets_FormChanged();
	elseif event == "SPELLS_CHANGED" then 
		return StanceSets_SpellsChanged();
	elseif event == "VARIABLES_LOADED" then
		StanceSets_UpdateLock();
	end
end

function StanceSets_SlashCmd(cmd)
	if cmd and cmd == "next" then
		return StanceSets_Next();
	end
	
	return StanceSets_Toggle();
end

function StanceSets_Toggle()
	if StanceSetsFrame:IsVisible() then
		HideUIPanel(StanceSetsFrame);
	else
		ShowUIPanel(StanceSetsFrame);
	end
end

function StanceSets_SpellsChanged()
	-- Spells have changed, this may mean that we've got a new shapeshift form
	if StanceSetsFrame:IsVisible() then
		return StanceSets_UpdateAllStances();
	end
end

function StanceSet_SetButtonTextureAndName(suffix,texture,itemName)
	local btn = getglobal("StanceSetsFrameSet"..suffix);
	if btn then
		SetItemButtonTexture(btn, texture);
		btn.itemName = itemName;
	end
end

function StanceSet_FindAndSetButtonTexture(suffix, itemName)
	if itemName and itemName ~= "" then
		local bag, slot = WeaponQuickSwap_FindItem(itemName);
		if bag and slot then
			local texture;
			if bag == -1 then
				texture = GetInventoryItemTexture("player", slot);
			else
				texture = GetContainerItemInfo(bag, slot);
			end
			StanceSet_SetButtonTextureAndName(suffix, texture, itemName);
		else
			-- if not found, just use a generic icon
			StanceSet_SetButtonTextureAndName(suffix, "Interface\\Icons\\INV_Misc_Gift_01", itemName);
		end
	else
		-- no item name, no icon
		StanceSet_SetButtonTextureAndName(suffix, nil, itemName);
	end
end

function StanceSets_UpdateAllStances()
	local allstances = StanceSets_GetAllForms();
	
	for i=1,STANCESET_MAX_STANCES do
		local stanceName = allstances[i];
		local frameStance = getglobal("StanceSetsFrameSet"..i);
		local frameLabel = getglobal("StanceSetsFrameSet"..i.."Title");
		
		if frameStance then
			local chkForceFirst = getglobal(frameStance:GetName().."ForceFirst");

			if stanceName then
				frameStance.StanceName = stanceName;
				
				frameStance:Show();
				if frameLabel then frameLabel:SetText(stanceName); end
				
				local playerName = UnitName("player");
				local setName = playerName.."_"..stanceName;
				local stanceSet = StanceSets[setName];
				
				if StanceSets[setName.."_ForceFirst"] then
					chkForceFirst:SetChecked(1);
				else
					chkForceFirst:SetChecked(nil);
				end
				
				if stanceSet then
				  StanceSet_FindAndSetButtonTexture(i.."MainHand1", stanceSet[1]);
				  StanceSet_FindAndSetButtonTexture(i.."OffHand1", stanceSet[2]);
				  StanceSet_FindAndSetButtonTexture(i.."MainHand2", stanceSet[3]);
				  StanceSet_FindAndSetButtonTexture(i.."OffHand2", stanceSet[4]);
				  StanceSet_FindAndSetButtonTexture(i.."MainHand3", stanceSet[5]);
				  StanceSet_FindAndSetButtonTexture(i.."OffHand3", stanceSet[6]);
				else
					StanceSet_SetButtonTextureAndName(i.."MainHand1", nil, nil);
					StanceSet_SetButtonTextureAndName(i.."OffHand1", nil, nil);
					StanceSet_SetButtonTextureAndName(i.."MainHand2", nil, nil);
					StanceSet_SetButtonTextureAndName(i.."OffHand2", nil, nil);
					StanceSet_SetButtonTextureAndName(i.."MainHand3", nil, nil);
					StanceSet_SetButtonTextureAndName(i.."OffHand3", nil, nil);
				end
			else				
				frameStance:Hide();
			end
		end  -- if frame found
	end  -- for i 1,MAX
end

function StanceSets_GetCurrentStanceSet()
	if not StanceSets then return end

	local currentForm = StanceSets_GetCurrentForm();
	local playerName = UnitName("player");
	
	if not playerName then return; end  -- player name might not be defined if not logged yet

	local setName = playerName.."_"..currentForm;
	return StanceSets[setName], setName;
end

function StanceSets_Next()
	local playerFormSet = StanceSets_GetCurrentStanceSet();
	if playerFormSet then
		for i = 1,6 do
			if not playerFormSet[i] and playerFormSet[i+1] then
				playerFormSet[i] = "";
			end
		end
						
		return WeaponSwap(unpack(playerFormSet));
	end
end

function StanceSets_FormChanged()
	local playerFormSet, setName = StanceSets_GetCurrentStanceSet();
	if playerFormSet then
		if StanceSets[setName.."_ForceFirst"] then
			-- must have at least one thing to do a swap
			if playerFormSet[1] or playerFormSet[2] then
				return WeaponSwap(playerFormSet[1], playerFormSet[2]);
			end
		elseif table.getn(playerFormSet) > 0 then
			-- If not forcing a set, only swap if we don't already a known set currently engaged
			local matchingsetidx = WeaponQuickSwap_FindCurrentSetIndex(16, 17, 1, playerFormSet);
			if not matchingsetidx then
				return WeaponSwap(unpack(playerFormSet));
			end
		end
	end
end

function StanceSets_GetCurrentForm()
	for i=1,GetNumShapeshiftForms(),1 do
		local _, name, isActive = GetShapeshiftFormInfo(i);
		if isActive then
			return name;
		end
	end
	
	return "Default";
end

function StanceSets_GetAllForms()
	local retVal = { };
	table.insert(retVal, "Default");
	for i=1,GetNumShapeshiftForms() do
		local _, name = GetShapeshiftFormInfo(i);
		table.insert(retVal, name);
	end
	
	return retVal;
end

function StanceSetSlot_OnEnter()
	if this.itemName and this.itemName ~= "" then
		GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
		
		local bag,slot = WeaponQuickSwap_FindItem(this.itemName);
		if bag and slot then
			if bag == -1 then
				GameTooltip:SetInventoryItem("player", slot);
			else
				GameTooltip:SetBagItem(bag,slot);
			end
		else
			GameTooltip:SetText(this.itemName, 1.0, 1.0, 1.0);
		end
		
		GameTooltip:Show();
	end
end

function StanceSetSlot_IDToSlotID(id)
	if id == 1 or id == 3 or id == 5 then
		return 16;
	else
		return 17;
	end
end

function StanceSetSlot_OnDragStart()
	local frmParent = this:GetParent();
	local playerName = UnitName("player");
	local setName = playerName.."_"..frmParent.StanceName;
	
	local stanceSet = StanceSets[setName];
	if stanceSet then
		stanceSet[this:GetID()] = nil;
		ResetCursor();
		StanceSets_UpdateAllStances();
	end
end

function StanceSetSlot_TakeItemOffCursor(srcBag, srcSlot)
	if srcBag == -1 then
		PickupInventoryItem(srcSlot);
	else
		PickupContainerItem(srcBag, srcSlot);
	end
end

function StanceSetSlot_OnReceiveDrag()
	StanceSetSlot_OnClick("LeftButton");
end

function StanceSetSlot_OnClick(arg1)
	local slotID = StanceSetSlot_IDToSlotID(this:GetID());
	
	arg1 = arg1 or "";
	if arg1 == "LeftButton" then
		if CursorHasItem() and StanceSets_PickedupItem then
			local itemName = WeaponQuickSwap_GetItemName(StanceSets_PickedupItem.bag, StanceSets_PickedupItem.slot);
				
			if CursorCanGoInSlot(slotID) then
				local frmParent = this:GetParent();
				local playerName = UnitName("player");
				local setName = playerName.."_"..frmParent.StanceName;
		
				local stanceSet = StanceSets[setName];
				if not stanceSet then stanceSet = {}; end
				stanceSet[this:GetID()] = itemName;
				StanceSets[setName] = stanceSet;
					
				StanceSets_UpdateAllStances();
			else
				Print(itemName.." can not go in that slot!");
			end
	
			ResetCursor();
			StanceSetSlot_TakeItemOffCursor(StanceSets_PickedupItem.bag,StanceSets_PickedupItem.slot);
		end  -- if has item and we know where it came from

		StanceSets_PickedupItem = nil;	
	end  -- if left button
end
--OK So these 2 functions are commented as they taint the execution path and cause an Action Blocked Error when trying to DE or use an item such as poisons from your inventory on an equipped item.
-- The fixed versions of them are below.
--[[
local StanceSets_Save_PickupContainerItem = PickupContainerItem;
PickupContainerItem = function (bag,slot)
	StanceSets_PickedupItem = { };
	StanceSets_PickedupItem.bag = bag;
	StanceSets_PickedupItem.slot = slot;
	return StanceSets_Save_PickupContainerItem(bag,slot);
end
]]--

--[[
local StanceSets_Save_PickupInventoryItem = PickupInventoryItem;
PickupInventoryItem = function (slot)
	StanceSets_PickedupItem = { };
	StanceSets_PickedupItem.bag = -1;
	StanceSets_PickedupItem.slot = slot;
	return StanceSets_Save_PickupInventoryItem(slot);
end
]]--

hooksecurefunc("PickupContainerItem", function (bag,slot)
    StanceSets_PickedupItem = { };
    StanceSets_PickedupItem.bag = bag;
    StanceSets_PickedupItem.slot = slot;
    end
);

hooksecurefunc("PickupInventoryItem", function (slot)
	StanceSets_PickedupItem = { };
	StanceSets_PickedupItem.bag = -1;
	StanceSets_PickedupItem.slot = slot;
	end
);

function StanceSetsForceCheck_OnClick()
	local frmParent = this:GetParent();
	local playerName = UnitName("player");
	local setName = playerName.."_"..frmParent.StanceName.."_ForceFirst";
	
	if not StanceSets then StanceSets = { }; end
	
	if (this:GetChecked()) then
		StanceSets[setName] = true;
		PlaySound("igMainMenuOptionCheckBoxOff");
	else
		StanceSets[setName] = nil;
		PlaySound("igMainMenuOptionCheckBoxOn");
	end
end

function DebugReport(msg, color, bSecondChatWindow)
	local r = 0.50;
	local g = 0.50;
	local b = 1.00;

	if (color) then
		r = color.r;
		g = color.g;
		b = color.b;
	end

	local frame = DEFAULT_CHAT_FRAME;
	if (bSecondChatWindow) then
		frame = ChatFrame2;
	end

	if (frame) then
		frame:AddMessage(msg,r,g,b);
	end
end
